﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.ServiceModel.Description;
using System.Windows.Forms;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Discovery;

namespace Crm2011.Connect
{
    public partial class CrmConnectionStringControl : UserControl
    {
        public CrmConnectionStringControl()
        {
            InitializeComponent();
            _errorProviders = new ErrorProviderCollection(this);
        }



        private readonly ErrorProviderCollection _errorProviders;


        /// <summary>
        /// Gets the CRM connection string based on the controls.
        /// </summary>
        /// <returns></returns>
        public CrmConnectionString GetCrmConnectionString()
        {
            return new CrmConnectionString
            {
                Url = textWebApplicationUrl.Text,
                Username = textUsername.Text,
                Password = (checkDefaultLogonCredentials.Checked) ? null : textPassword.Text,
                Domain = textDomain.Text,
                DiscoveryUrl = textDiscoveryUrl.Text,
                OrganizationUrl = textOrganizationUrl.Text,
            };
        }


        /// <summary>
        /// Sets the CRM connection string and populates the controls accordingly
        /// </summary>
        /// <param name="value">The value.</param>
        public void SetCrmConnectionString(CrmConnectionString value)
        {
            CrmConnectionString crmConnectionString = value ?? new CrmConnectionString();
            textDiscoveryUrl.Text = crmConnectionString.DiscoveryUrl ?? crmConnectionString.Url;
            textUsername.Text = crmConnectionString.Username;
            textPassword.Text = crmConnectionString.Password;
            textDomain.Text = crmConnectionString.Domain;
            checkDefaultLogonCredentials.Checked = crmConnectionString.DefaultCredentials;
        }


        private OrganizationDetail SelectedOrganization
        {
            get { return (comboOrganizations.SelectedItem != null) ? comboOrganizations.SelectedItem as OrganizationDetail : null; }
        }



        #region UI Event-Handlers


        private void btnConnectDiscoveryClick(object sender, EventArgs e)
        {
            _errorProviders.ClearAllErrors();
            comboOrganizations.Items.Clear();
            comboOrganizations.Enabled = false;
            try
            {
                //ClientCredentials credentials = new ClientCredentials();

                //case AuthenticationProviderType.ActiveDirectory:
                //    this._proxy.ClientCredentials.UserName.UserName = null;
                //    this._proxy.ClientCredentials.UserName.Password = null;
                //    break;
                //case AuthenticationProviderType.Federation:
                //case AuthenticationProviderType.LiveId:
                //    this._proxy.ClientCredentials.Windows.ClientCredential = null;
                //    break;

                AuthenticationProviderType endpointType = AuthenticationProviderType.ActiveDirectory;

                CrmConnectionString crmConnectionString = this.GetCrmConnectionString();
                AuthenticationCredentials authCredentials = new AuthenticationCredentials();
                
                switch (endpointType)
                {
                    case AuthenticationProviderType.ActiveDirectory:
                        authCredentials.ClientCredentials.Windows.ClientCredential =
                            crmConnectionString.DefaultCredentials
                            ? null
                            : new System.Net.NetworkCredential(crmConnectionString.Username, crmConnectionString.Password, crmConnectionString.Domain);
                        break;

                    case AuthenticationProviderType.LiveId:
                        authCredentials.ClientCredentials.UserName.UserName = crmConnectionString.Username;
                        authCredentials.ClientCredentials.UserName.Password = crmConnectionString.Password;
                        //authCredentials.SupportingCredentials = new AuthenticationCredentials();
                        //authCredentials.SupportingCredentials.ClientCredentials = Microsoft.Crm.Services.Utility.DeviceIdManager.LoadOrRegisterDevice();
                        break;
                }

                //credentials.Windows.ClientCredential =
                //    crmConnectionString.DefaultCredentials
                //    ? null
                //    : new NetworkCredential(crmConnectionString.Username, crmConnectionString.Password, crmConnectionString.Domain);
                //IEnumerable<OrganizationDetail> orgs = getOrganizations(credentials);
                IEnumerable<OrganizationDetail> orgs = getOrganizations(authCredentials.ClientCredentials);
                foreach (var organization in orgs)
                {
                    comboOrganizations.Items.Add(organization);
                }
                comboOrganizations.DisplayMember = "FriendlyName";
                comboOrganizations.Enabled = true;
                comboOrganizations.Focus();
            }
            catch (Exception exception)
            {
                _errorProviders.SetError(this.btnConnectDiscovery, exception.Message);
            }
        }



        private void comboOrganizationsSelectedIndexChanged(object sender, EventArgs e)
        {
            OrganizationDetail org = this.SelectedOrganization;
            textOrganizationUrl.Text = org.Endpoints[EndpointType.OrganizationService];
            textWebApplicationUrl.Text = org.Endpoints[EndpointType.WebApplication];
        }



        private void checkDefaultLogonCredentialsCheckedChanged(object sender, EventArgs e)
        {
            panelUserinfo.Enabled = !checkDefaultLogonCredentials.Checked;
        }


        #endregion



        #region Local helpers


        private Uri getDiscoveryServiceUrl()
        {
            return new Uri(String.Format("{0}/XRMServices/2011/Discovery.svc", textDiscoveryUrl.Text));
        }




        private IEnumerable<OrganizationDetail> getOrganizations(ClientCredentials credentials)
        {
            using (var discoveryService = new DiscoveryServiceProxy(getDiscoveryServiceUrl(), null, credentials, null))
            {
                var retrieveOrgsRequest = new RetrieveOrganizationsRequest
                    {
                        AccessType = EndpointAccessType.Default,
                        Release = OrganizationRelease.Current
                    };
                var response = (RetrieveOrganizationsResponse)discoveryService.Execute(retrieveOrgsRequest);
                return response.Details.Where(od => od.State == OrganizationState.Enabled);
            }
        }


        #endregion

    }
}